package net.pws.common.security.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.pws.common.security.spi.AuthenticateProvider;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;


public class AuthenticateProcessor extends AbstractAuthenticateFilter implements
		InitializingBean {

	private AuthenticateProvider authenticateProvider;

	private ClientVersionProvider clientVersionProvider;
	
	private CaptchaValidator captchaValidator;
	
	private LoginLogProvider loginLogProvider;

	private JsonAuthenticateProcessorHandler jsonAuth;

	private WebAuthenticateProcessorHandler webAuth;

	public AuthenticateProvider getAuthenticateProvider() {
		return authenticateProvider;
	}

	public void setAuthenticateProvider(
			AuthenticateProvider authenticateProvider) {
		this.authenticateProvider = authenticateProvider;
		initHandlers();
	}

	public ClientVersionProvider getClientVersionProvider() {
		return clientVersionProvider;
	}

	public void setClientVersionProvider(
			ClientVersionProvider clientVersionProvider) {
		this.clientVersionProvider = clientVersionProvider;
		initHandlers();
	}

	public CaptchaValidator getCaptchaValidator() {
        return captchaValidator;
    }

    public void setCaptchaValidator(CaptchaValidator captchaValidator) {
        this.captchaValidator = captchaValidator;
        initHandlers();
    }
    
	public LoginLogProvider getLoginLogProvider() {
		return loginLogProvider;
	}

	public void setLoginLogProvider(LoginLogProvider loginLogProvider) {
		this.loginLogProvider = loginLogProvider;
		initHandlers();
	}

    public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		if (!(request instanceof HttpServletRequest)) {
			throw new ServletException("Can only process HttpServletRequest");
		}

		if (!(response instanceof HttpServletResponse)) {
			throw new ServletException("Can only process HttpServletResponse");
		}

		HttpServletRequest httpRequest = (HttpServletRequest) request;
		HttpServletResponse httpResponse = (HttpServletResponse) response;

		if (!required(httpRequest, httpResponse)) {
			chain.doFilter(request, response);
			return;
		}

		if ("by-json".equalsIgnoreCase(determineAuthType(request))) {
			jsonAuth.doFilter(request, response, chain);
			return;
		}

		webAuth.doFilter(request, response, chain);
	}

	private void initHandlers() {
		if (jsonAuth == null) {
			jsonAuth = new JsonAuthenticateProcessorHandler();
		}
		if (webAuth == null) {
			webAuth = new WebAuthenticateProcessorHandler();
		}
		jsonAuth.setAuthenticateProvider(authenticateProvider);
		jsonAuth.setClientVersionProvider(clientVersionProvider);
		jsonAuth.setLoginLogProvider(loginLogProvider);
		webAuth.setAuthenticateProvider(authenticateProvider);
		webAuth.setCaptchaValidator(captchaValidator);
		webAuth.setLoginLogProvider(loginLogProvider);
	}

	private boolean required(HttpServletRequest request,
			HttpServletResponse response) {
		return matches(request, response, getSecurityCheckUrl());
	}

	public void afterPropertiesSet() throws Exception {
		Assert.notNull(authenticateProvider);
	}

}
